#include "UI.h"

_UI::_UI()
{
    type = UI_str;
    selectNum = 0;
    specialSelector = 0;

}

void _UI::show()
{
    if(type == UIType::UI_str)
    {
        for(std::vector<UIElement> middle : data)
        {
            for(UIElement data : middle)
            {
                setcolor(data.wordcolor, data.backgroundcolor);
                if(data.type == _int)
                    std::cout << *data.dataint;
                else if(data.type == _float)
                    std::cout << *data.datafloat;
                else if(data.type == _str)                        
                    std::cout << *data.datastr;
                else if(data.type == _conststring)
                    std::cout << data._conststring;
                else if(data.type == _bool)
                {
                    if(*data.databool)
                        std::cout << "是";
                    else
                        std::cout << "否";
                }
                resetcolor();
            }
            std::cout << "\n";
        }   
    }
    else if(type == UIType::UI_selector)
    {
        for(int i = 0;i < data.size();i++)
        {
            if(i == selectNum)
                std::cout << "*";
            else
                std::cout << "  ";
            if(i == specialSelector)
            {
                std::cout << "√";
            }
            for(UIElement data : data[i])
            {
                setcolor(data.backgroundcolor, data.backgroundcolor);
                if(data.type == _int)
                    std::cout << *data.dataint;
                else if(data.type == _float)
                    std::cout << *data.datafloat;
                else if(data.type == _str)                        
                    std::cout << *data.datastr;
                else if(data.type == _conststring)
                    std::cout << data._conststring;
                else if(data.type == _bool)
                {
                    if(*data.databool)
                        std::cout << "是";
                    else
                        std::cout << "否";
                }
                resetcolor();
            }
            std::cout << "\n";
        }
    }
    
}

void _UI::addstr(std::string (*_data),bool _endl, int wordcolor, int backgroundcolor)
{
    UIElement middle;
    middle.type = _str;
    middle.datastr = _data;
    middle.wordcolor = wordcolor;
    middle.backgroundcolor = backgroundcolor;
    if(LineCompleteFlag)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
        LineCompleteFlag = 0;
    }
    data[data.size() - 1].emplace_back(middle);
    if(_endl)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
    }
}

void _UI::addfloat(float (*_data),bool _endl, int wordcolor, int backgroundcolor)
{
    UIElement middle;
    middle.type = _float;
    middle.datafloat = _data;
    middle.wordcolor = wordcolor;
    middle.backgroundcolor = backgroundcolor;
    if(LineCompleteFlag)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
        LineCompleteFlag = 0;
    }
    data[data.size() - 1].emplace_back(middle);
    if(_endl)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
    }
}

void _UI::addint(int (*_data),bool _endl, int wordcolor, int backgroundcolor)
{
    UIElement middle;
    middle.type = _int;
    middle.dataint = _data;
    middle.wordcolor = wordcolor;
    middle.backgroundcolor = backgroundcolor;
    if(LineCompleteFlag)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
        LineCompleteFlag = 0;
    }
    data[data.size() - 1].emplace_back(middle);
    if(_endl)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
    }
}

void _UI::addconststring(std::string _data,bool _endl, int wordcolor, int backgroundcolor)
{
    UIElement middle;
    middle.type = _conststring;
    middle._conststring = _data;
    middle.wordcolor = wordcolor;
    middle.backgroundcolor = backgroundcolor;
    if(LineCompleteFlag)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
        LineCompleteFlag = 0;
    }
    data[data.size() - 1].emplace_back(middle);
    if(_endl)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
    }
}

void _UI::addbool(bool* _data,bool _endl, int wordcolor, int backgroundcolor)
{
    UIElement middle;
    middle.type = _bool;
    middle.databool = _data;
    middle.wordcolor = wordcolor;
    middle.backgroundcolor = backgroundcolor;
    if(LineCompleteFlag)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
        LineCompleteFlag = 0;
    }
    data[data.size() - 1].emplace_back(middle);
    if(_endl)
    {
        std::vector<UIElement> _middle;
        data.emplace_back(_middle);
    }
}

void _UI::clear()
{
    data.clear();
    std::vector<UIElement> _middle;
    data.emplace_back(_middle);
}

void _UI::setcolor(int wordcolor, int backgroundcolor)
{
    if (wordcolor ==  0)
    {
        wordcolor = 7;
    }
#ifdef __APPLE__
    int R = 0;
    int G = 0;
    int B = 0;
    if (wordcolor >= 8)
    {
        wordcolor -= 8;
    }
    if (wordcolor >= 4)
    {
        wordcolor -= 4;
        R = 255;
    }
    if (wordcolor >= 2)
    {
        wordcolor -= 2;
        G = 255;
    }
    if (wordcolor >= 1)
    {
        B = 255;
    }
    std::cout << "\x1B[38;2;" << R << ";" << G << ";" << B << "m";

    R = 0;
    G = 0;
    B = 0;
    if (backgroundcolor >= 8)
    {
        backgroundcolor -= 8;
    }
    if (backgroundcolor >= 4)
    {
        backgroundcolor -= 4;
        R = 255;
    }
    if (backgroundcolor >= 2)
    {
        backgroundcolor -= 2;
        G = 255;
    }
    if (backgroundcolor >= 1)
    {
        B = 255;
    }
    std::cout << "\x1B[48;2;" << R << ";" << G << ";" << B << "m";
#elif defined(__linux__)
    int R = 0;
    int G = 0;
    int B = 0;
    if (wordcolor >= 8)
    {
        wordcolor -= 8;
    }
    if (wordcolor >= 4)
    {
        wordcolor -= 4;
        R = 255;
    }
    if (wordcolor >= 2)
    {
        wordcolor -= 2;
        G = 255;
    }
    if (wordcolor >= 1)
    {
        B = 255;
    }
    std::cout << "\x1B[38;2;" << R << ";" << G << ";" << B << "m";

    R = 0;
    G = 0;
    B = 0;
    if (backgroundcolor >= 8)
    {
        backgroundcolor -= 8;
    }
    if (backgroundcolor >= 4)
    {
        backgroundcolor -= 4;
        R = 255;
    }
    if (backgroundcolor >= 2)
    {
        backgroundcolor -= 2;
        G = 255;
    }
    if (backgroundcolor >= 1)
    {
        B = 255;
    }
    std::cout << "\x1B[48;2;" << R << ";" << G << ";" << B << "m";
#else
    char mask = 0;
    if (wordcolor >= 8)
    {
        wordcolor -= 8;
        mask |= FOREGROUND_INTENSITY;
    }
    if (wordcolor >= 4)
    {
        wordcolor -= 4;
        mask |= FOREGROUND_RED;
    }
    if (wordcolor >= 2)
    {
        wordcolor -= 2;
        mask |= FOREGROUND_GREEN;
    }
    if (wordcolor >= 1)
    {
        B = 255;
        mask |= FOREGROUND_BLUE;
    }
    if (backgroundcolor >= 8)
    {
        backgroundcolor -= 8;
        mask |= BACKGROUND_INTENSITY;
    }
    if (backgroundcolor >= 4)
    {
        backgroundcolor -= 4;
        mask |= BACKGROUND_RED;
    }
    if (backgroundcolor >= 2)
    {
        backgroundcolor -= 2;
        mask |= BACKGROUND_GREEN;
    }
    if (backgroundcolor >= 1)
    {
        mask |= BACKGROUND_BLUE;
    }
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, mask);
#endif
}

void _UI::resetcolor()
{
#ifdef __APPLE__
    std::cout << "\x1B[0m";
#elif defined(__linux__)
    std::cout << "\x1B[0m";
#else
    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#endif
}

int  KeyboardOperate()
{
    int key = 0;
    while(1)
    {
        key = _getch();
        //72上 80下 27esc 83回车
        if(key == KEY_UP||key==KEY_DOWN||key==KEY_ESC||key==KEY_ENTER)
            return key;
    }
}

void clearUI()
{   
#ifdef __APPLE__
    system("clear");
#elif defined(__linux__)
    system("clear");
#else 
    system("cls");
#endif
}

void PrintUI(std::vector<_UI> _data)
{
    for(int i = 0;i < _data.size();i++)
    {
        _data[i].show();
    }
}

#ifdef __APPLE__
int _getch()
{
    struct termios oldattr, newattr;
    int ch;
    tcgetattr(STDIN_FILENO, &oldattr);
    newattr = oldattr;
    newattr.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newattr);
    ch = getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldattr);
    return ch;
}
#elif defined(__linux__)
int _getch()
{
    struct termios oldattr, newattr;
    int ch;
    tcgetattr(STDIN_FILENO, &oldattr);
    newattr = oldattr;
    newattr.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newattr);
    ch = getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldattr);
    return ch;
}
#endif